#include "stdafx.h"
#include "SmartPointers.h"
#include "NamedMockData.h"

#include <memory>
#include <iostream>
#include <vector>
#include <algorithm>


std::unique_ptr<NamedMockData<char>> generateOnePtrInstance()
{
	std::unique_ptr<NamedMockData<char>> local(new NamedMockData<char>);

	// It will cause move operation since it's returned by a local value, 
	// which matches the RValue reference constructor
	return local;
}

std::unique_ptr<NamedMockData<char>> func(std::unique_ptr<NamedMockData<char>>& data)
{
	// It will cause copy operation since it's returned by a LValue reference.
	// It will cause a compile error since unique_ptr private the copy constructor
	//return data;

	return std::unique_ptr<NamedMockData<char>>();
}

void UniquePtrPassAsValueAction(void)
{
	std::cout << "Start to get the intance with a unique_ptr smart point" << std::endl;
	// It's like : int&& i = 32
	// It calls RValue reference assign operator consturctor
	auto ret = generateOnePtrInstance();

	std::cout << "Try to call the print func" << std::endl;
	ret->Print();

	std::cout << "End of the action" << std::endl;
}

// In this case, you should use shared_ptr as a substitution choice.
void UniquePtrVectorCopyAction(void)
{
	std::vector<std::unique_ptr<NamedMockData<char>>> v(10);
	std::generate(std::begin(v), std::end(v), [&]() { return generateOnePtrInstance(); });

	// Check if v has pass the ownership to v1, Actually it's now allowed, good job!
	// It's also said, bellow code uses vector's assign operator copy constructor, nor the move constructor.
	//std::vector<std::unique_ptr<NamedMockData<char>>> v1 = v;

	// And you can not use the copy and assign operator copy contructor for unique_ptr class, well done!
	// So in lambda parameter, you have to pass the reference but value.
	std::for_each(std::begin(v), std::end(v), [&](const std::unique_ptr<NamedMockData<char>>& data){ data->Print(); });
	//std::for_each(std::begin(v1), std::end(v1), [&](const std::unique_ptr<NamedMockData<char>>& data){ data->Print(); });
	std::cout << "End of the action" << std::endl;
}


